#include "Config/Config.h"
#include "../botpch.h"
#include "playerbot.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotFactory.h"
#include "AccountMgr.h"
#include "ObjectMgr.h"
#include "DatabaseEnv.h"
#include "PlayerbotAI.h"
#include "Player.h"
#include "RandomPlayerbotFactory.h"
#include "SystemConfig.h"

map<uint8, vector<uint8> > RandomPlayerbotFactory::availableRaces;

RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(accountId)
{
	availableRaces[CLASS_WARRIOR].push_back(RACE_HUMAN);
	availableRaces[CLASS_WARRIOR].push_back(RACE_NIGHTELF);
	availableRaces[CLASS_WARRIOR].push_back(RACE_GNOME);
	availableRaces[CLASS_WARRIOR].push_back(RACE_DWARF);
	availableRaces[CLASS_WARRIOR].push_back(RACE_ORC);
	availableRaces[CLASS_WARRIOR].push_back(RACE_UNDEAD);
	availableRaces[CLASS_WARRIOR].push_back(RACE_TAUREN);
	availableRaces[CLASS_WARRIOR].push_back(RACE_TROLL);

	availableRaces[CLASS_PALADIN].push_back(RACE_HUMAN);
	availableRaces[CLASS_PALADIN].push_back(RACE_DWARF);

	availableRaces[CLASS_ROGUE].push_back(RACE_HUMAN);
	availableRaces[CLASS_ROGUE].push_back(RACE_DWARF);
	availableRaces[CLASS_ROGUE].push_back(RACE_NIGHTELF);
	availableRaces[CLASS_ROGUE].push_back(RACE_GNOME);
	availableRaces[CLASS_ROGUE].push_back(RACE_ORC);
	availableRaces[CLASS_ROGUE].push_back(RACE_TROLL);

	availableRaces[CLASS_PRIEST].push_back(RACE_HUMAN);
	availableRaces[CLASS_PRIEST].push_back(RACE_DWARF);
	availableRaces[CLASS_PRIEST].push_back(RACE_NIGHTELF);
	availableRaces[CLASS_PRIEST].push_back(RACE_TROLL);
	availableRaces[CLASS_PRIEST].push_back(RACE_UNDEAD);

	availableRaces[CLASS_MAGE].push_back(RACE_HUMAN);
	availableRaces[CLASS_MAGE].push_back(RACE_GNOME);
	availableRaces[CLASS_MAGE].push_back(RACE_UNDEAD);
	availableRaces[CLASS_MAGE].push_back(RACE_TROLL);

	availableRaces[CLASS_WARLOCK].push_back(RACE_HUMAN);
	availableRaces[CLASS_WARLOCK].push_back(RACE_GNOME);
	availableRaces[CLASS_WARLOCK].push_back(RACE_UNDEAD);
	availableRaces[CLASS_WARLOCK].push_back(RACE_ORC);

	availableRaces[CLASS_SHAMAN].push_back(RACE_ORC);
	availableRaces[CLASS_SHAMAN].push_back(RACE_TAUREN);
	availableRaces[CLASS_SHAMAN].push_back(RACE_TROLL);

	availableRaces[CLASS_HUNTER].push_back(RACE_DWARF);
	availableRaces[CLASS_HUNTER].push_back(RACE_NIGHTELF);
	availableRaces[CLASS_HUNTER].push_back(RACE_ORC);
	availableRaces[CLASS_HUNTER].push_back(RACE_TAUREN);
	availableRaces[CLASS_HUNTER].push_back(RACE_TROLL);

	availableRaces[CLASS_DRUID].push_back(RACE_NIGHTELF);
	availableRaces[CLASS_DRUID].push_back(RACE_TAUREN);
}

bool RandomPlayerbotFactory::CreateRandomBot(uint8 cls)
{
	sLog.outDetail("Creating new random bot for class %d", cls);

	//uint8 gender = rand() % 2 ? GENDER_MALE : GENDER_FEMALE;
	uint8 gender;
	string name;
	if (!CreateRandomBotName(cls, name, gender)) {
		return false;
	}
	
	if (name.empty())
		return false;

	uint8 race = availableRaces[cls][urand(0, availableRaces[cls].size() - 1)];

	uint8 skin = urand(0, 7);
	uint8 face = urand(0, 7);
	uint8 hairStyle = urand(0, 7);
	uint8 hairColor = urand(0, 7);
	uint8 facialHair = urand(0, 7);
	uint8 outfitId = 0;

	WorldSession* session = new WorldSession(accountId, NULL, SEC_PLAYER, 0, LOCALE_enUS);
	if (!session)
	{
		sLog.outError("Couldn't create session for random bot account %d", accountId);
		delete session;
		return false;
	}

	Player *player = new Player(session);
	if (!player->Create(sObjectMgr.GeneratePlayerLowGuid(), name, race, cls, gender, skin, face, hairStyle, hairColor, facialHair, outfitId))
	{
		player->DeleteFromDB(player->GetObjectGuid(), accountId, true, true);
		delete session;
		delete player;
		sLog.outError("Unable to create random bot for account %d - name: \"%s\"; race: %u; class: %u; gender: %u; skin: %u; face: %u; hairStyle: %u; hairColor: %u; facialHair: %u; outfitId: %u",
			accountId, name.c_str(), race, cls, gender, skin, face, hairStyle, hairColor, facialHair, outfitId);
		return false;
	}

	player->setCinematic(2);
	player->SetAtLoginFlag(AT_LOGIN_NONE);
	player->SaveToDB();

	sLog.outDetail("Random bot created for account %d - name: \"%s\"; race: %u; class: %u; gender: %u; skin: %u; face: %u; hairStyle: %u; hairColor: %u; facialHair: %u; outfitId: %u",
		accountId, name.c_str(), race, cls, gender, skin, face, hairStyle, hairColor, facialHair, outfitId);

	return true;
}

bool RandomPlayerbotFactory::CreateRandomBotName(uint8 cls, string &name, uint8 &gender)
{
	//QueryResult *result = CharacterDatabase.Query("SELECT MAX(name_id) FROM ai_playerbot_names");
	//if (!result)
	//	return "";

	//Field *fields = result->Fetch();
	//uint32 maxId = fields[0].GetUInt32();
	//delete result;

	//uint32 id = urand(0, maxId);
	QueryResult *result = CharacterDatabase.PQuery("SELECT n.name,n.gender FROM ai_playerbot_names n LEFT OUTER JOIN characters e ON e.name = n.name WHERE e.guid IS NULL AND n.class = '%u' LIMIT 1", cls);
	if (!result)
	{
		sLog.outError("No more names left for random bots");
		return false;
	}

	Field *nfields = result->Fetch();
	name = nfields[0].GetCppString();
	gender = nfields[1].GetUInt8();
	delete result;

	return true;
}

